/**
 * @brief 定时器封装
 */

#ifndef __TIME_H__
#define __TIME_H__

#include <memory>
#include <vector>
#include <set>
#include <functional>
#include "mutex.h"

// 所谓定时器，就是给调度协程预设一个协程对象，等定时时间到了就恢复预设的协程对象

class TimerManager;
// 定时器
class Timer : public std::enable_shared_from_this<Timer>
{
    friend class TimerManager;

public:
    typedef std::shared_ptr<Timer> ptr;

    bool cancel();
    bool refresh();
    bool reset(uint64_t ms, bool from_now);

private:
    Timer(uint64_t ms, std::function<void()> cb, bool recurring, TimerManager *manager);

    Timer(uint64_t next);

private:
    // 是否循环定时
    bool m_recurring = false;
    // 执行周期
    uint64_t m_ms = 0;
    // 精确的执行时间
    uint64_t m_next = 0;
    // 回调函数
    std::function<void()> m_cb;
    // 定时器管理器
    TimerManager *m_manager = nullptr;

private:
    // 定时器比较仿函数
    struct Comparator
    {
        bool operator()(const Timer::ptr &lptr, const Timer::ptr &rptr) const;
    };
};

// 定时器管理器

class TimerManager
{
    friend class Timer;

public:
    typedef RWMutex RWMutexType;

    TimerManager();
    virtual ~TimerManager();

    // 添加定时器
    Timer::ptr addTimer(uint64_t ms, std::function<void()> cb, bool recurring = false);

    // 添加条件定时器
    Timer::ptr addConditionTimer(uint64_t ms, std::function<void()> cb,
                                 std::weak_ptr<void> weak_cond, bool recurring = false);

    // 到下一个定时器执行的时间间隔ms
    uint64_t getNextTimer();

    // 获取需要执行的定时器的回调函数列表
    void listExpireCb(std::vector<std::function<void()>> &cbs);

    // 是否有定时器
    bool hasTimer();

protected:
    // 当有新的定时器插入到定时器的首部,执行该函数
    virtual void onTimerInsertAtFront() = 0;

    // 将定时器添加到管理器中
    void addTimer(Timer::ptr val, RWMutexType::WriteLock &lock);

    // 检测服务器时间是否被调后了
    bool delectClockRollover(uint64_t now_ms);

private:
    RWMutexType m_mutex;
    // 定时器集合
    std::set<Timer::ptr, Timer::Comparator> m_timers;

    // 是否触发onTimerInsertAtFront
    bool m_tickled = false;
    // 上次执行时间
    uint64_t m_previousTime = 0;
};

#endif